package com.hightrast.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hightrast.service.api.baseEntity.exception.ServiceException;
import com.hightrast.service.api.domain.qo.rastProducts.QueryProductCountQo;
import com.hightrast.service.api.domain.qo.rastProducts.QueryRastProductsQo;
import com.hightrast.service.api.domain.qo.rastProducts.UpdateProductQo;
import com.hightrast.service.api.domain.vo.rastOrderItem.QueryCountChartData;
import com.hightrast.service.api.domain.vo.rastOrderItem.QueryProductCountVo;
import com.hightrast.service.api.domain.vo.rastProduct.QueryRastProductsVo;
import com.hightrast.service.api.entity.*;
import com.hightrast.service.api.enums.RoleTypeEnum;
import com.hightrast.service.compareToData.EntitySynchronizer;
import com.hightrast.service.compareToData.stage.impl.*;
import com.hightrast.service.mapper.RastProductsMapper;
import com.hightrast.service.service.*;
import com.hightrast.service.util.BaseEntityUtil;
import com.hightrast.service.util.SecureUtil;
import com.hightrast.service.util.TreeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author hx
 * @since 2025-01-22
 */
@Service
@Slf4j
public class RastProductsServiceImpl extends ServiceImpl<RastProductsMapper, RastProducts> implements IRastProductsService {


    @Resource
    IRastUserRoleService userRoleService;
    @Resource
    IRastUserVendorService userVendorService;
    @Resource
    IRastProductVariantsService productVariantsService;
    @Resource
    IRastProductImagesService productImagesService;
    @Value("${commissonRate:20}")
    private BigDecimal commissonRate;
    @Resource
    IRastVendorService vendorService;

//    private ExecutorService executorService = Executors.newFixedThreadPool(4);

    /**
     * 查询商品列表 根据角色 以及当前用户绑定的品牌，如果管理者角色查询所有商品
     */
    @Override
    public IPage<QueryRastProductsVo> queryProducts(QueryRastProductsQo qo) {
        RastUser user = SecureUtil.getUser();
        // 是否存在管理者角色
        RastUserRole rastUserRole = userRoleService.queryUserRoleByUserId(user.getId()).stream().filter(a -> a.getRoleType().equals(RoleTypeEnum.ADMIN.getValue())).findFirst().orElse(null);
        qo.setUserId(qo.getSelectUserId());
        IPage<QueryRastProductsVo> page = new Page<>(qo.getPage(), qo.getPageSize());
        if (Objects.isNull(rastUserRole)) {
            log.info("进入非管理者查询商品，查询当前用户关联的品牌的商品");
            qo.setUserId(user.getId());
        }
//        if(StringUtils.isNotEmpty(qo.getOrderField()) && qo.getOrderField().equals("userName")){
//            qo.setOrderField("vendor");
//        }
        // 获取商品列表
        IPage<QueryRastProductsVo> productsVos = this.baseMapper.selectProducts(page, qo);
//        if (CollectionUtil.isNotEmpty(productsVos.getRecords())) {
//            if (Objects.nonNull(rastUserRole)) {
//                log.info("进入管理者组装人");
//                List<String> vendors = productsVos.getRecords().stream().map(QueryRastProductsVo::getVendor).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
//
//                // 获取这些品牌关联的人
//                Map<String, String> userVendorMap = userVendorService.queryUserVendors(vendors).stream().collect(Collectors.toMap(RastUserVendor::getVendor, RastUserVendor::getUserName, (v1, v2) -> v1));
//
//                productsVos.getRecords().forEach(product -> {
//                    Optional.ofNullable(userVendorMap.get(product.getVendor()))
//                            .ifPresent(product::setUserName);
//                });
//
//            } else {
//                log.info("进入非管理者组装人");
//                productsVos.getRecords().forEach(product -> product.setUserName(user.getUserName()));
//            }
//        }
        return productsVos;
    }


    /**
     * 修改商品成本、佣金比例
     */
    @Override
    public void updateProducts(UpdateProductQo qo) {
        RastUser user = SecureUtil.getUser();
        RastProductVariants products = Optional.ofNullable(productVariantsService.getById(qo.getVariableId()))
                .orElseThrow(() -> new ServiceException("The current product does not exist"));
        if (qo.getPrice() != null) {
            if (Objects.isNull(products.getSampleCost())) {
                // 当前商品未定义样品成本，不能修改商品售价
                throw new ServiceException("The current product does not have a defined sample cost, and the selling price cannot be modified");
            }
            if (qo.getPrice().compareTo(products.getSampleCost()) < 0) {
                // 设置商品价格不能低于样品成本价格
                throw new ServiceException("Set the product price to not be lower than the sample cost price");
            }
        }
        LocalDateTime now = LocalDateTime.now();
        if (qo.getCommissonRate() != null || qo.getSampleCost() != null) {
            // 成本和佣金率只有管理者账号才能修改
            // 是否存在管理者角色
            RastUserRole rastUserRole = userRoleService.queryUserRoleByUserId(user.getId()).stream().filter(a -> a.getRoleType().equals(RoleTypeEnum.ADMIN.getValue())).findFirst().orElse(null);
            if (Objects.isNull(rastUserRole)) {
                // 角色不匹配
                throw new ServiceException("Role Mismatch");
            }
        }

        productVariantsService.update(new LambdaUpdateWrapper<RastProductVariants>()
                .set(qo.getPrice() != null, RastProductVariants::getPrice, qo.getPrice())
                .set(qo.getCommissonRate() != null, RastProductVariants::getCommissonRate, qo.getCommissonRate())
                .set(qo.getCommissonRate() != null, RastProductVariants::getCommissonRateDate, now)
                .set(qo.getSampleCost() != null, RastProductVariants::getSampleCost, qo.getSampleCost())
                .set(qo.getPrice() != null || qo.getCommissonRate() != null || qo.getSampleCost() != null, RastProductVariants::getModifyId, user.getId())
                .set(qo.getPrice() != null || qo.getCommissonRate() != null || qo.getSampleCost() != null, RastProductVariants::getModifyTime, now)
                .eq(RastProductVariants::getId, qo.getVariableId()));
    }

    @Override
    public List<String> queryProductType() {
        return this.list().stream().map(RastProducts::getProductType).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void addProduct(List<RastProducts> rastProducts) {
        if (CollectionUtils.isEmpty(rastProducts)) {
            log.info("新增商品数据为空");
            return;
        }
        rastProducts.forEach(a -> a.setCommissonRate(commissonRate));

//        // 更新商品
//        CompletableFuture<Void> productFuture = CompletableFuture.runAsync(() -> {
//            try {
                List<RastProducts> oldProducts = this.list();
                //对比数据更新
                EntitySynchronizer.syncEntities(rastProducts,
                        oldProducts,
                        RastProducts::getId,
                        this::updateBatchById,
                        this::saveBatch,
                        this::removeByIds,
                        new RastProductComparator(),
                        new RastProductUpdater());
//            } catch (Exception e) {
//                log.info("处理商品数据时出现异常: " + e.getMessage());
//                throw new RuntimeException("处理商品数据时出现异常", e);
//            }
//        }, executorService);

        // 更新商品变体
//        CompletableFuture<Void> variantFuture = CompletableFuture.runAsync(() -> {
//            try {
                // 添加商品变体
                List<RastProductVariants> productVariants = rastProducts.stream()
                        .flatMap(pd -> pd.getVariants().stream())
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(productVariants)) {
                    List<RastProductVariants> oldVariants = productVariantsService.list();
                    //对比数据更新
                    EntitySynchronizer.syncEntities(productVariants,
                            oldVariants,
                            RastProductVariants::getId,
                            productVariantsService::updateBatchById,
                            productVariantsService::saveBatch,
                            productVariantsService::removeByIds,
                            new RastProductVariantComparator(),
                            new RastProductVariantUpdater());
                }
//            } catch (Exception e) {
//                log.info("处理商品变体数据时出现异常: " + e.getMessage());
//                throw new RuntimeException("处理商品变体数据时出现异常", e);
//            }
//        }, executorService);

//        // 更新商品图片
//        CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
//            try {
                // 添加商品图片
                List<RastProductImages> productImages = rastProducts.stream()
                        .flatMap(pd -> pd.getImages().stream())
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(productImages)) {
                    // 新数据
                    productImages = productImages.stream().filter(TreeUtils.distinctByKey(RastProductImages::getId)).collect(Collectors.toList());
                    // 原数据
                    List<RastProductImages> oldImages = productImagesService.list();
                    //对比数据更新
                    EntitySynchronizer.syncEntities(productImages,
                            oldImages,
                            RastProductImages::getId,
                            productImagesService::updateBatchById,
                            productImagesService::saveBatch,
                            productImagesService::removeByIds,
                            new RastProductImagesComparator(),
                            new RastProductImagesUpdater());
                }
//            } catch (Exception e) {
//                log.info("处理商品图片数据时出现异常: " + e.getMessage());
//                throw new RuntimeException("处理商品图片数据时出现异常", e);
//            }
//        }, executorService);

        // 更新品牌
//        CompletableFuture<Void> vendorFuture = CompletableFuture.runAsync(() -> {
//            try {
                // 添加品牌
                List<String> vendors = rastProducts.stream().map(RastProducts::getVendor).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
                List<String> oldVendors = vendorService.list().stream().map(RastVendor::getVendor).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(oldVendors)) {
                    vendors = vendors.stream().filter(a -> !oldVendors.contains(a)).collect(Collectors.toList());
                }
                List<RastVendor> addVendors = vendors.stream().map(a -> {
                    RastVendor vendor = new RastVendor();
                    vendor.setVendor(a);
                    BaseEntityUtil.save(vendor);
                    return vendor;
                }).collect(Collectors.toList());

                if (CollectionUtil.isNotEmpty(addVendors)) {
                    vendorService.saveBatch(addVendors);
                }
//            } catch (Exception e) {
//                log.info("处理品牌数据时出现异常: " + e.getMessage());
//                throw new RuntimeException("处理品牌数据时出现异常", e);
//            }
//        }, executorService);

//        CompletableFuture<Void> allFutures = CompletableFuture.allOf(productFuture, variantFuture, imageFuture, vendorFuture);
//        try {
//            allFutures.join();
//        } catch (Exception e) {
//            // 所有任务完成后，若有异常则统一处理
//            log.info("整体数据处理出现异常: " + e.getMessage());
//            throw new RuntimeException("整体数据处理出现异常", e);
//        } finally {
//            executorService.shutdown();
//        }
    }


    @Override
    public QueryCountChartData queryProductCount(QueryProductCountQo qo) {
        RastUser user = SecureUtil.getUser();
        // 是否存在管理者角色
        RastUserRole rastUserRole = userRoleService.queryUserRoleByUserId(user.getId()).stream().filter(a -> a.getRoleType().equals(RoleTypeEnum.ADMIN.getValue())).findFirst().orElse(null);
        if (Objects.isNull(rastUserRole)) {
            log.info("进入非管理者查询，查询当前用户数据");
            qo.setUserId(user.getId());
        }
        if (null == qo.getStartDate() || null == qo.getEndDate()) {
            // 如果时间参数为空，默认查询当月至今数据
            LocalDate now = LocalDate.now();
            LocalDate firstDay = LocalDate.of(now.getYear(), now.getMonth(), 1);
            qo.setStartDate(firstDay);
            qo.setEndDate(now);
        }

        QueryCountChartData countChartData = new QueryCountChartData();
        List<QueryProductCountVo> queryProductCountVos = this.baseMapper.selectProductCount(qo);

        Map<LocalDate, QueryProductCountVo> queryProductCountMap = queryProductCountVos.stream().collect(Collectors.toMap(QueryProductCountVo::getSaleDate, Function.identity()));
        List<LocalDate> dateRange = new ArrayList<>();
        List<BigDecimal> dailyCosts = new ArrayList<>();
        List<BigDecimal> dailySales = new ArrayList<>();
        // 从起始日期开始遍历到结束日期
        for (LocalDate date = qo.getStartDate(); !date.isAfter(qo.getEndDate()); date = date.plusDays(1)) {
            dateRange.add(date);
            QueryProductCountVo currentDateCount = queryProductCountMap.get(date);
            if (Objects.nonNull(currentDateCount)) {
                dailyCosts.add(currentDateCount.getDailyCost());
                dailySales.add(currentDateCount.getDailySales());
            } else {
                dailyCosts.add(BigDecimal.valueOf(0));
                dailySales.add(BigDecimal.valueOf(0));
            }
        }
        countChartData.setXAxisData(dateRange);

        Map<String, List<BigDecimal>> seriesData = new HashMap<>();
        seriesData.put("profitData", dailyCosts);
        seriesData.put("salesData", dailySales);
        countChartData.setSeriesData(seriesData);
        return countChartData;
    }

}
